﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using HyperLocal.Core;
using System.Linq.Expressions;

namespace HyperLocal.Model
{
    public class Repository
    {

        public HyperLocalDataContext DC { get; set; }

        public Repository()
        {
            DC = new HyperLocalDataContext();
        }
        public Repository(String connString)
        {
            DC = new HyperLocalDataContext(connString);
        }

        /// <summary>
        /// Return all instances of type T.
        /// </summary>
        /// <returns></returns>
        public IQueryable<T> All<T>() where T : class
        {
            return DC.GetTable<T>();
        }



        /// <summary>
        /// Return all instances of type T that match the expression exp.
        /// </summary>
        /// <param name="exp"></param>
        /// <returns></returns>
        public IQueryable<T> Find<T>(Expression<Func<T, bool>> exp) where T : class
        {
            return DC.GetTable<T>().Where<T>(exp);
        }

        public IEnumerable<T> FindBySql<T>(string query) where T : class
        {
           return DC.ExecuteQuery<T>(query);
        }

        /// <summary>See IRepository</summary>
        /// <param name="exp"></param>
        /// <returns></returns>
        public T Single<T>(Expression<Func<T, bool>> exp) where T : class
        {
            return DC.GetTable<T>().SingleOrDefault(exp);
        }

        /// <summary>See IRepository</summary>
        /// <param name="exp"></param>
        /// <returns></returns>
        public virtual T First<T>(Expression<Func<T, bool>> exp) where T : class
        {
            return DC.GetTable<T>().First(exp);
        }

        /// <summary>See IRepository</summary>
        /// <param name="entity"></param>
        public virtual void Delete<T>(T entity) where T : class
        {
            DC.GetTable<T>().DeleteOnSubmit(entity);
            DC.SubmitChanges();
        }

        /// <summary>
        /// Create a new instance of type T.
        /// </summary>
        /// <returns></returns>
        public virtual T New<T>() where T : class
        {
            T entity = Activator.CreateInstance<T>();
            DC.GetTable<T>().InsertOnSubmit(entity);
            DC.SubmitChanges();
            return entity;
        }

        /// <summary>
        /// Adds an insance T.
        /// </summary>
        /// <returns></returns>
        public virtual T Insert<T>(T entity) where T : class
        {
            DC.GetTable<T>().InsertOnSubmit(entity);
            DC.SubmitChanges();
            return entity;
        }

        /// <summary>
        /// Update entity.
        /// </summary>
        /// <returns></returns>
        public virtual void Update<T>(T entity) where T : class
        {
            DC.Refresh(System.Data.Linq.RefreshMode.KeepCurrentValues, entity);
            DC.SubmitChanges();
        }

        /// <summary>See IRepository</summary>
        public void SubmitChanges<T>() where T : class
        {
            DC.SubmitChanges();
        }
    }
}
